/*
 * Copyright (c) China Telecom Cloud Technology Co., Ltd. 2024-2025. All rights reserved.
 */
#ifndef LRU_MANAGER_H
#define LRU_MANAGER_H

#include <cstdint>
#include <cstddef>
#include <list>
#include <vector>
#include <unordered_map>
#include "KvcBaseDefine.h"
#include <list>
#include <vector>
#include <unordered_map>
#include <mutex>
#include "Segment.h"

#if defined(USE_GPU)
#include <cuda_runtime.h>
#endif

// TODO(yangxianpku: 2025.08.21):  移除typedef模式
typedef struct {
    int64_t  segmentId;  // Segment对象id
    uint64_t offset;     // Segment相对于共享内存池的偏移

    // TODO(yangxianpku: 2025.08.21):  考虑使用int64_t或size_t
    int32_t  idx;        // Segment在全局SegList中的索引
} SegMeta;


using SegmentId = int64_t;



class LRUManager {
private:
    //! 的insert, del为O(1), 结合map是的find也为O(1)
    std::list<SegMeta> _lruQueue;         // 记录访问顺序，用于LRU淘汰

    // 记录指定Segment在_lruQueue中的位置
    std::unordered_map<SegmentId,         // SegmengID
            std::list<SegMeta>::iterator  // Sgement 在_lruQueue中的位置迭代器
        > _lruMap;                        // _lruQueue的位置(迭代器索引)

public:
    LRUManager() = default;

    /**
     *! @brief 
     * 
     */
    void init();


    /**
     *! @brief 插入一个SegMeta对象到_lruQueue中，如果存在先删除
     * 
     * @param segmentId  Segment对象id
     * @param offset     Segment相对于共享内存池的偏移
     * @param idx        Segment在SegList中的索引
     */
    void insert(int64_t  segmentId, 
                uint64_t offset, 
                int32_t  idx
            );


    /**
     *! @brief 清除segmentId对应信息，同步清除_lruQueue和_lruMap
     * 
     * @param segmentId 
     */
    void remove(int64_t segmentId);



    // TODO(yangxianpku: 2025.08.18): 该方法未实现
    std::vector<int32_t> evict(int32_t needEvictNum);



    /**
     *! @brief segmentId信息是否存在_lruMap中
     * 
     * @param segmentId 
     * @return bool
     */
    bool contain(int64_t segmentId);


    /**
     *! @brief 获取segmentId的内存偏移(相对内存池基地址)
     * 
     * @param segmentId 
     * @return uint64_t 
     */
    uint64_t getOffsetBySegmentId(int64_t segmentId);


    /**
     *! @brief 获取Segment在全局SegList中的索引
     * 
     * @param segmentId 
     * @return uint64_t 
     */
    uint64_t getIdxBySegmentId(int64_t segmentId);


    /**
     *! @brief 按照过滤条件逐出一些segment到freeList(segment需要存活一定时间，TTL内的不能驱逐)
     * 
     * @param segList     Segment列表，用于判断是否可以逐出
     * @param freeList    空闲块列表(uint64_t)是Segment的offset
     * @param proposeNum  需要逐出的segment数量
     * @param actualNum   实际逐出的segment数量
     */
    // TODO(yangxianpku: 2025.08.21): 考虑增加返回本次驱逐的Segment列表
    void evict(std::vector<Segment> &segList, 
                std::list<uint64_t> &freeList, 
                int32_t proposeNum, 
                int32_t &actualNum
            );


    /**
     *! @brief 获取_lruQueue中所有isFilled的Segment信息
     * 
     * @param segList 
     * 
     * @return std::vector<BlockHashId> 
     */
    std::vector<BlockHashId> getAllFilledSegmentIds(
                    std::vector<Segment> &segList);



    /**
     *! @brief 将segmentIds对应的SegMeta移动到末尾，segmentIds内还是保持先后顺序
     *
     * @param segmentIds 
     */
    void reorder(std::vector<int64_t> &segmentIds);



    void print(std::vector<Segment> &segList);


    /**
     * @brief 清除_lruQueue和_lruMap
     * 
     */
    void clean();
};

#endif  // LRU_MANAGER_H